package com.korion.andsurfacewallpaperdemo.gl

import android.content.Context
import android.opengl.GLES11Ext
import android.opengl.GLES20
import android.util.Log
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader

class ShaderHelper {
    companion object {
        private const val TAG = "ShaderHelper"
        
        fun loadShader(context: Context, shaderType: Int, resourceId: Int): Int {
            val shaderSource = readShaderFromAssets(context, resourceId)
            return compileShader(shaderType, shaderSource)
        }
        
        fun buildProgram(vertexShaderSource: String, fragmentShaderSource: String): Int {
            val vertexShader = compileShader(GLES20.GL_VERTEX_SHADER, vertexShaderSource)
            val fragmentShader = compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderSource)
            
            val program = GLES20.glCreateProgram()
            if (program == 0) {
                Log.e(TAG, "Could not create program")
                return 0
            }
            
            GLES20.glAttachShader(program, vertexShader)
            GLES20.glAttachShader(program, fragmentShader)
            GLES20.glLinkProgram(program)
            
            val linkStatus = IntArray(1)
            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0)
            if (linkStatus[0] != GLES20.GL_TRUE) {
                Log.e(TAG, "Could not link program: ")
                Log.e(TAG, GLES20.glGetProgramInfoLog(program))
                GLES20.glDeleteProgram(program)
                return 0
            }
            
            return program
        }
        
        private fun compileShader(type: Int, shaderSource: String): Int {
            val shader = GLES20.glCreateShader(type)
            if (shader == 0) {
                Log.e(TAG, "Could not create shader")
                return 0
            }
            
            GLES20.glShaderSource(shader, shaderSource)
            GLES20.glCompileShader(shader)
            
            val compileStatus = IntArray(1)
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0)
            if (compileStatus[0] == 0) {
                Log.e(TAG, "Could not compile shader: ")
                Log.e(TAG, GLES20.glGetShaderInfoLog(shader))
                GLES20.glDeleteShader(shader)
                return 0
            }
            
            return shader
        }
        
        fun readShaderFromAssets(context: Context, resourceId: Int): String {
            val inputStream = context.resources.openRawResource(resourceId)
            val bufferedReader = BufferedReader(InputStreamReader(inputStream))
            var line: String?
            val body = StringBuilder()
            
            try {
                while (bufferedReader.readLine().also { line = it } != null) {
                    body.append(line).append("\n")
                }
                inputStream.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
            
            return body.toString()
        }
    }
}